home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
nt
/
zkf102.zip
/
extend.txt
< prev
next >
Wrap
Text File
|
1995-01-04
|
7KB
|
148 lines
C++ Language Extensions Added by ZK
The c++ language is extended by zk to add a few minor features, such
as new kinds of macros, which peacefully coexist with the standard
"#define" macros, and which make it easier to implement a command
shell without asking the user to type excess characters at the
command line. For example, to implement a typical command line
command such as "copy *.txt c:\txt" using normal c++ macros would
require excessive syntax such as "copy(*.txt,c:\\txt)", but by using
the new kinds of macros provided by zk, it can be implemented such
that the command the user types at the zk command line looks exactly
the same as when typed at the operating system command line.
There are two new kinds of macros, #m and #m1. They work similarly to
#define, but with different syntax and features. #define is unchanged.
#m macroname(arguments)
macro definition
%
The % has to be the last character on the last line of the macro. You
don't need backslashes at the ends of lines as you do in #define macros.
So you always need a % at the end of every #m macro, even if it's just
one line, e.g. #m tmac(arg1,arg2) definition text %
The formal arguments are the same as for #define, except that you can
also use an asterisk as the last formal argument, for the vararg feature.
The actual arguments can be the same as for a #define macro, except that
the opening parenthesis has to touch the macro name, with no white space
between them. But instead of that you can use use a new syntax, which
is improved and preferred, in which the arguments follow the macro name
with no parentheses and are separated by white space. For example, if
the definition is #m abc(x) x x % then the call can be abc(123) or
abc 123 but not abc (123) because that would result in (123) (123)
instead of 123 123. See some of the examples later in this document
(extend.txt) to clarify this.
The vararg feature uses an asterisk as the rightmost formal argument,
and invokes that argument from within the macro by using the name vararg,
or varargfirst or varargrest. The cmds macro, shown later in this
document, is an example to clarify this. When the name vararg appears
in a macro that uses this feature, it is replaced with all the text of
all the arguments that take the place of the asterisk in the formals.
The other two, varargfirst and varargrest, are for parsing that text,
giving the first and rest of those arguments. Recursion, as used in
the cmds macro, makes such parsing work for indefinite lists.
When a macro uses the vararg feature and is called using the whitespace
syntax (i.e., no parentheses), the actual argument list needs to be
terminated to prevent it from extending to the end of the file. Such
termination is provided by a semicolon, which is consumed by the macro.
Thus if you need a semicolon at the end of a statement implemented by
such a macro, you should put it in the macro definition to avoid having
to put two semicolons at the end of the macro call. This only applies
to macros that use the vararg feature.
#m1 is the same as #m except that the macro call has to be at the start
of a C++ statement or declaration. That reduces the probability that
the macro name will conflict with names of variables, etc. It's useful
for defining commands to use at the command line.
The command line has an implied semicolon at the end, but it only applies
in contexts where appropriate. That is, only when you are typing in
commands for immediate execution and a semicolon is expected; Otherwise
the command continues to the next line. If you don't want an implied
semicolon at that point, even though a semicolon is expected, you can
continue the command to the next line explicitly with a backslash. Try
it yourself to understand which contexts are affected. The whole purpose
of this feature is to reduce your typing when typing simple commands, so
it will be like an ordinary command shell for that purpose.
Here are some example macros, discussed further below:
#m1 sys(*) xsystem(#vararg); nop(); %
#m def1cmd(cmd)
#m1 cmd(*) sys cmd vararg; %%
%
#m1 cmds(*)
#if #varargfirst[0]
def1cmd varargfirst
cmds varargrest;
#endif
%
The sys macro use the vararg feature and calls a function named xsystem,
which is an interface to the compiler vendor's system function, which
executes an operating system command. The nop() function does nothing,
and its only purpose is to cause the last function on the command line
to return void (to return nothing) because some types of return values
are displayed automatically by zk, such as when you type in an expression
and want to see the result. The nop() causes the return value of xsystem
to not be displayed. It's the return value of system, and is normally
not very useful in this context, and would confuse the output.
The def1cmd macro is used by the cmds macro to define one command. The
double %% is how a nested macro definition is terminated, to not confuse
it with the single % terminating the outer macro.
The cmds macro calls itself recursively, once per argument. See the
discussion earlier in this document for an explanation of the vararg
feature. The #varargfirst[0] stringizes the first argument and takes
its first character, and if that's 0, it means the stringize result is
empty, which means there is no first argument, which means the whole
argument list has been processed by the recursion.
In general, you can copy the style of the cmds macro to make other
recursive macros that work the same way, even if you don't understand
some of the more subtle points explained here. Don't get confused by
the stringizing. The # attached to the start of the names vararg and
varargfirst causes their results to be stringized, which means to
enclose them in quotation marks and do any processing needed to make
them legal string literals. And don't get confused by the
#varargfirst[0], which translates to ""[0] when the argument list is
exhausted. ""[0] is 0, because strings are terminated by a 0, and an
empty string is terminated at [0], and that's how the cmds macro knows
when to stop processing arguments.
Another added preprocessor feature is #H, which is a like #include, but
only works with zk header files, *.zh, and which has slightly neater
syntax. If you have three header files named one.zh, two,zh, and
three.zh, the normal #include syntax is three lines:
#include "one.zh"
#include "two.zh"
#include "three.zh"
But the #H syntax is just one line:
#H one two three
(with the .zh extensions omitted, because #H adds them internally.)
Also, using the #H feature, even just once in your program, turns on a
flag which causes all header files used by your program, even those using
#include, to only be processed once, regardless of how many times they
are referenced. This is normally desirable, because processing the same
header file more than once is normally a waste of time, even if it has
protection causing it to be skipped after the first time, because just
reading it and skipping through it takes time, even if not very much.
But in general the #H feature is not very significant and you can safely
ignore it, and use #include instead.